<template>
    <div>
        <el-form label-width="100px">
            <el-form-item label="SPU名称">
                <el-input placeholder="SPU名称" v-model="spuInfo.spuName" />
            </el-form-item>
            <el-form-item label="品牌">
                <el-select placeholder="请选择品牌名" v-model="spuInfo.tmId">
                    <el-option :label="item.tmName" v-for="item in trademarkList" :value="item.id" :key="item.id" />
                </el-select>
            </el-form-item>
            <el-form-item label="SPU描述">
                <el-input type="textarea" placeholder="SPU描述" v-model="spuInfo.description" />
            </el-form-item>
            <el-form-item label="SPU图片">
                <el-upload
                    v-model:file-list="spuImageList"
                    :action="`${baseUrl}/admin/product/upload`"
                    list-type="picture-card"
                    :on-preview="handlePictureCardPreview"
                    :on-remove="handleRemove"
                    :on-success="handleSuccess"
                >
                    <el-icon>
                        <Plus />
                    </el-icon>
                </el-upload>
                <el-dialog v-model="dialogVisible">
                    <img w-full :src="item.imgUrl" alt="Preview Image" v-for="item in spuImageList" :key="item.id" />
                </el-dialog>
            </el-form-item>
            <el-form-item label="销售属性">
                <el-select :placeholder="`还有${unSelectedSaleAttrList.length}未选择`" v-model="saleAttrIdName">
                    <el-option :label="item.name" :value="`${item.id}:${item.name}`" v-for="item in unSelectedSaleAttrList" :key="item.id" />
                </el-select>
                <el-button type="primary" size="default" style="margin-left: 5px" @click="addSaleAttr" :disabled="!saleAttrIdName">添加销售属性</el-button>
                <el-table border stripe :data="spuSaleAttrList" style="margin-top: 20px">
                    <el-table-column type="index" width="80" label="序号" />
                    <el-table-column label="属性名" prop="saleAttrName"></el-table-column>
                    <el-table-column label="属性值名称列表" width="500" prop="spuSaleAttrValueList">
                        <template #default="{ row }">
                            <el-tag v-for="(item, index) in row.spuSaleAttrValueList" :key="item.id" closable @close="row.spuSaleAttrValueList.splice(index, 1)">
                                {{ item.saleAttrValueName }}
                            </el-tag>
                            <el-input class="input-new-tag" ref="saveTagInput" size="small" v-if="row.isEdit" v-model="row.inputValue" @blur="handleInputConfirm(row)"></el-input>
                            <el-button class="button-new-tag" size="small" v-else @click="showInput(row)">添加属性值</el-button>
                        </template>
                    </el-table-column>
                    <el-table-column label="操作">
                        <template v-slot="{ $index }">
                            <el-button type="danger" size="small" @click="spuSaleAttrList.splice($index, 1)" title="删除" icon="ele-Delete"></el-button>
                        </template>
                    </el-table-column>
                </el-table>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" @click="save">保存</el-button>
                <el-button @click="cancel">取消</el-button>
            </el-form-item>
        </el-form>
    </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
    name: "SpuForm",
});
</script>

<script setup lang="ts">
import { Plus } from "@element-plus/icons-vue";
import type { UploadFile, UploadFiles, UploadProps } from "element-plus";
import { computed, nextTick, onMounted, ref } from "vue";
import { ElMessage } from "element-plus";
import type { BaseSaleAttrListType, SpuImageListType, SpuInfoType, SpuSaleAttrItemType, SpuSaleAttrListType, SpuSaleAttrValueItemType } from "@/types/spu";
import type { TrademarkType } from "@/types/trademark";
import { reqGetAllTrademark } from "@/api/trademark";
import { reqAddSpu, reqBaseSaleAttrList, reqSpuImageList, reqSpuSaleAttrList, reqUpdateSpu } from "@/api/spu";

// 接收父组件传递的自定义事件
const emit = defineEmits(["changeShowState"]);
// 取消按钮的回调
const cancel = () => {
    emit("changeShowState", 1);
};
// 接收父组件传递的props
const props = defineProps<{ spuInfo: SpuInfoType }>();

/*
 * @Description: 初始化数据
 * */
// 1.初始化trademarkList数据
const trademarkList = ref<TrademarkType[]>([]);
// 2.初始化baseSaleAttrList数据
const baseSaleAttrList = ref<BaseSaleAttrListType>([]);
// 3.初始化spuImageList数据
const spuImageList = ref<SpuImageListType>([]);
// 4.初始化spuSaleAttrList数据
const spuSaleAttrList = ref<SpuSaleAttrListType>([]);

/*
 * @Description: 获取数据
 * */

// 1.初始化添加spu页面的数据
const getInitAddSpuData = async () => {
    try {
        // 1.1获取所有trademarkList数据
        trademarkList.value = await reqGetAllTrademark();
        // 1.2获取所有销售属性数据
        baseSaleAttrList.value = await reqBaseSaleAttrList();
    } catch (e: any) {
        ElMessage.error(e.message);
    }
};
// 2.初始化修改spu页面的数据
const getInitUpdateSpuData = async () => {
    // 2.1获取所有trademarkList数据
    const result1 = reqGetAllTrademark();
    // 2.2获取所有销售属性数据
    const result2 = reqBaseSaleAttrList();
    // 2.3获取所有spuImageList数据
    const result3 = reqSpuImageList(props.spuInfo.id as number);
    // 2.4获取所有spuSaleAttrList数据
    const result4 = reqSpuSaleAttrList(props.spuInfo.id as number);
    try {
        // 2.5当所有数据都获取成功后，才赋值(并发请求)
        const result = await Promise.all([result1, result2, result3, result4]);
        trademarkList.value = result[0];
        baseSaleAttrList.value = result[1];
        spuImageList.value = result[2];
        spuSaleAttrList.value = result[3];
        // 图片回显
        spuImageList.value.forEach(item => {
            item.name = item.imgName;
            item.url = item.imgUrl;
        });
    } catch (e: any) {
        ElMessage.error(e.message);
    }
};
// 3.初始化数据
onMounted(() => {
    if (props.spuInfo.id) {
        getInitUpdateSpuData();
    } else {
        getInitAddSpuData();
    }
});
/*
 * @Description: 上传图片的配置
 * */
const baseUrl = import.meta.env.VITE_API_URL; //上传路径前缀
const dialogImageUrl = ref("");
const dialogVisible = ref(false);
const handleRemove: UploadProps["onRemove"] = (uploadFile, uploadFiles) => {
    // 删除的时候,uploadFiles就是最新的数据
    spuImageList.value = uploadFiles as unknown as SpuImageListType;
};

const handlePictureCardPreview: UploadProps["onPreview"] = uploadFile => {
    dialogImageUrl.value = uploadFile.url!;
    dialogVisible.value = true;
};
const handleSuccess = (response: any, uploadFile: UploadFile, uploadFiles: UploadFiles) => {
    console.log(response, uploadFile, uploadFiles);
    // 上传成功后,将图片的信息添加到spuImageList中
    spuImageList.value = uploadFiles as unknown as SpuImageListType;
    // 优化imageList的数据
    props.spuInfo.spuImageList = spuImageList.value.map(item => {
        return {
            imgName: item.name as string,
            imgUrl: response.data, // 上传成功后,图片的地址在response中
        };
    });
};

/*
 * @description: 销售属性和销售属性值的配置
 * */
// 销售属性的计算
const unSelectedSaleAttrList = computed(() => {
    //根据所有的销售属性列表和spu自己的销售属性列表去计算产生未使用的销售属性列表
    //从所有的销售属性中过滤，过滤不在spu自己的销售属性列表中的所有内容
    return baseSaleAttrList.value.filter(baseSaleAttr => {
        //判断当前的baseSaleAttr是否在spuSaleAttrList中
        //如果在，返回false，表示不要
        //如果不在，返回true，表示要
        return !spuSaleAttrList.value.some(spuSaleAttr => {
            return spuSaleAttr.baseSaleAttrId === baseSaleAttr.id;
        });
    });
});
// 收集添加销售属性
const saleAttrIdName = ref("");
// 添加销售属性的回调
const addSaleAttr = () => {
    // 1.添加
    let [baseSaleAttrId, saleAttrName] = saleAttrIdName.value.split(":");
    let obj: SpuSaleAttrItemType = {
        baseSaleAttrId: +baseSaleAttrId,
        saleAttrName,
        spuSaleAttrValueList: [],
    };
    spuSaleAttrList.value.push(obj);
    // 2.清空
    saleAttrIdName.value = "";
};
// 收集添加销售属性值
const saveTagInput = ref<HTMLInputElement>(); //获取input元素
// 点击按钮切换表单模式
const showInput = (row: SpuSaleAttrItemType) => {
    row.isEdit = true;
    //自动获取焦点
    nextTick(() => {
        saveTagInput.value?.focus();
    });
};
// 失去焦点的回调函数
const handleInputConfirm = (row: SpuSaleAttrItemType) => {
    let saleAttrValueName = row.inputValue;
    //判断是否为空
    if (!saleAttrValueName || !saleAttrValueName.trim()) {
        row.inputValue = "";
        row.isEdit = false;
        return;
    }
    //判断是否有重复
    let isRepeat = row.spuSaleAttrValueList.some(item => item.saleAttrValueName === saleAttrValueName);
    if (isRepeat) {
        ElMessage.error("输入的属性值名称不能重复");
        row.inputValue = "";
        row.isEdit = false;
        return;
    }

    /*
        baseSaleAttrId?:number,需要代表属性值所属属性的id,给哪个属性加属性值
        saleAttrValueName:string,/需要代表属性值的名称
        id?:number,//不需要，因为新添加的销售属性值对象没有id
        isChecked:string,//不需要，因为这个数据后台不需要
        saleAttrName:string,/不需要，因为有了销售属性的id,就知道给哪个销售属性添加属性值
        spuId?:number//不需要新添加spu的时候没有id
    */

    //组装一个新的销售属性值
    let obj = {
        baseSaleAttrId: row.baseSaleAttrId,
        saleAttrValueName,
    };
    //把对象添加到指定位置
    row.spuSaleAttrValueList.push(<SpuSaleAttrValueItemType>obj);
    row.inputValue = "";
    row.isEdit = false;
};

/*
 * @description: 保存spu
 * */
const save = async () => {
    // 删除spuSaleAttrList上的isEdit和inputValue
    spuSaleAttrList.value.forEach(item => {
        delete item.isEdit;
        delete item.inputValue;
    });
    props.spuInfo.spuSaleAttrList = spuSaleAttrList.value; // 把spuSaleAttrList赋值给spuInfo,图片列表的数据已经处理过了
    // 保存
    try {
        if (props.spuInfo.id) {
            // 修改
            await reqUpdateSpu(props.spuInfo);
            ElMessage.success("修改成功");
        } else {
            // 添加
            await reqAddSpu(props.spuInfo);
            ElMessage.success("添加成功");
        }
        // 跳转到列表页
        emit("changeShowState", 1);
    } catch (e) {
        ElMessage.error("保存失败");
    }
};
</script>

<style scoped>
.avatar-uploader .avatar {
    width: 178px;
    height: 178px;
    display: block;
}
</style>

<style>
.avatar-uploader .el-upload {
    border: 1px dashed var(--el-border-color);
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
    border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    text-align: center;
}
</style>
